package com.rs.game.player.actions;

import java.util.HashMap;
import java.util.Map;

import com.rs.game.Animation;
import com.rs.game.player.Player;
import com.rs.game.player.Skills;
import com.rs.game.tasks.WorldTask;
import com.rs.game.tasks.WorldTasksManager;
import com.rs.utils.Utils;

/**
 * 
 * @author Swirl/Jacob <obruza@gmail.com>
 *
 */
public class Farming {
	public static int RAKE = 5341;
	public static int SEED_DIBBER = 5343;
	public static int SECATEURS = 5329;
	public static int SPADE = 952;
	public static int WEEDS = 6055;
	public static final Animation RAKE_ANIMATION = new Animation(2273);
	public static final Animation PLANT_ANIMATION = new Animation(2291);
	public static final Animation PICK_HERB = new Animation(2281);
	public static final Animation PICK_ALLOTMENT = new Animation(830);
	public static boolean raked;
	
	public static enum Patches {
		FALADOR_NORTH_ALLOTMENT(8550, 708),
		FALADOR_SOUTH_ALLOTMENT(8551, 709),
		FALADOR_HERB(8150, 780),
		FALADOR_FLOWER(7847, 728);
		
		public static Map<Integer, Patches> patches = new HashMap<Integer, Patches>();
		
		public static Patches forId(int id) {
			return patches.get(id);
		}
		
		static {
			for (Patches patch : Patches.values()) {
				patches.put(patch.objectId, patch);
			}
		}
		
		private int objectId;
		private int configId;
		
		Patches(int objectId, int configId) {
			this.objectId = objectId;
			this.configId = configId;
		}
		
		public int getObjectId() {
			return objectId;
		}
		
		public int getConfigId() {
			return configId;
		}
	}
	
	public static enum Herbs {
		GUAM(5291, 199, 9, 11, 12.5, 4),
		MARRENTILL(5292, 201, 14, 13.5, 15, 11),
		TARROMIN(5293, 203, 19, 16, 18, 18),
		HARRALANDER(5294, 205, 26, 21.5, 24, 25),
		RANARR(5295, 207, 32, 27, 30.5, 32),
		TOADFLAX(5296, 3049, 38, 34, 38.5, 39),
		IRIT(5297, 209, 44, 43, 48.5, 46),
		AVANTOE(5298, 211, 50, 54.5, 61.5, 53),
		WERGALI(14870, 14836, 46, 52.8, 52.8, 60),
		KWUARM(5299, 213, 56, 69, 78, 69),
		SNAPDRAGON(5300, 3051, 62, 87.5, 98.5, 75),
		CADANTINE(5301, 215, 67, 106.5, 120, 82),
		LANTADYME(5302, 2485, 73, 134.5, 151.5, 89),
		DWARF_WEED(5303, 217, 79, 170.5, 192, 96),
		TORSTOL(5304, 219, 85, 199.5, 22.5, 103),
		FELLSTALK(21621, 21626, 91, 225, 315.6, 103);
		
		private int seed;
		private int product;
		private int req;
		private double plantXp;
		private double harvestXp;
		private int configId;
		
		public static Map<Integer, Herbs> herbs = new HashMap<Integer, Herbs>();
		
		public static Herbs forId(int id) {
			return herbs.get(id);
		}
		
		static {
			for (Herbs herb : Herbs.values()) {
				herbs.put(herb.seed, herb);
			}
		}
		
		private Herbs(int seed, int product, int req, double plantXp, double harvestXp, int configId) {
			this.seed = seed;
			this.product = product;
			this.req = req;
			this.plantXp = plantXp;
			this.harvestXp = harvestXp;
			this.configId = configId;
		}
		
		public int getSeed() {
			return seed;
		}
		
		public int getProduct() {
			return product;
		}
		
		public int getReq() {
			return req;
		}
		
		public double getHarvestXp() {
			return harvestXp;
		}
		
		public double getPlantXp() {
			return plantXp;
		}
		
		public int getConfigId() {
			return configId;
		}
	}
	
	public static enum Allotments {
		POTATO(5318, 1942, 1, 8, 9, 6, 4),
		ONION(5319, 1957, 5, 9.5, 10.5, 13, 4),
		CABBAGE(5324, 1965, 7, 10, 11.5, 20, 4),
		TOMATOES(5322, 1982, 12, 12.5, 14, 27, 4),
		SWEETCORN(5320, 5986, 20, 17, 19, 34, 6),
		STRAWERRIES(5323, 5504, 31, 26, 29, 43, 6),
		WATERMELON(5321, 5982, 47, 48.5, 54.5, 52, 8);
		
		private int seed;
		private int product;
		private int req;
		private double plantXp;
		private double harvestXp;
		private int configId;
		private int stages;
		
		public static Map<Integer, Allotments> allotments = new HashMap<Integer, Allotments>();
		
		public static Allotments forId(int id) {
			return allotments.get(id);
		}
		
		static {
			for (Allotments allotment : Allotments.values()) {
				allotments.put(allotment.seed, allotment);
			}
		}
		
		private Allotments(int seed, int product, int req, double plantXp, double harvestXp, int configId, int stages) {
			this.seed = seed;
			this.product = product;
			this.req = req;
			this.plantXp = plantXp;
			this.harvestXp = harvestXp;
			this.configId = configId;
			this.stages = stages;
		}
		
		public int getSeed() {
			return seed;
		}
		
		public int getProduct() {
			return product;
		}
		
		public int getReq() {
			return req;
		}
		
		public double getHarvestXp() {
			return harvestXp;
		}
		
		public double getPlantXp() {
			return plantXp;
		}
		
		public int getConfigId() {
			return configId;
		}
		
		public int getStages() {
			return stages;
		}
	}
	
	public static enum Flowers {
		MARIGOLD(5096, 6010, 2, 8.5, 0, 8, 4),
		ROSEMARY(5097, 6014, 11, 12, 0, 13, 4),
		NASTURTIUM(5098, 6012, 24, 19.5, 0, 18, 4),
		WOAD(5099, 1793, 25, 20.5, 0, 23, 4),
		LIMPWURT(5100, 225, 26, 21.5, 18.5, 28, 5),
		LILY(14589, 14583, 52, 70, 0, 37, 4);
		
		private int seed;
		private int product;
		private int req;
		private double plantXp;
		private double harvestXp;
		private int configId;
		private int stages;
		
		public static Map<Integer, Flowers> flowers = new HashMap<Integer, Flowers>();
		
		public static Flowers forId(int id) {
			return flowers.get(id);
		}
		
		static {
			for (Flowers flower : Flowers.values()) {
				flowers.put(flower.seed, flower);
			}
		}
		
		private Flowers(int seed, int product, int req, double plantXp, double harvestXp, int configId, int stages) {
			this.seed = seed;
			this.product = product;
			this.req = req;
			this.plantXp = plantXp;
			this.harvestXp = harvestXp;
			this.configId = configId;
			this.stages = stages;
		}
		
		public int getSeed() {
			return seed;
		}
		
		public int getProduct() {
			return product;
		}
		
		public int getReq() {
			return req;
		}
		
		public double getHarvestXp() {
			return harvestXp;
		}
		
		public double getPlantXp() {
			return plantXp;
		}
		
		public int getConfigId() {
			return configId;
		}
		
		public int getStages() {
			return stages;
		}
	}
	
	public static void startRake(final Player player, final int objectId) {
		if (player.getInventory().containsItem(RAKE, 1)) {
			WorldTasksManager.schedule(new WorldTask() {
				int stage;
				Patches patch = Patches.forId(objectId);
				
				@Override
				public void run() {
					if (stage == 0) {
						player.lock();
						player.setNextAnimation(RAKE_ANIMATION);
						player.getPackets().sendConfigByFile(patch.getConfigId(), 1);
						player.getInventory().addItem(WEEDS, 1);
					} else if (stage == 3) {
						player.setNextAnimation(RAKE_ANIMATION);
						player.getPackets().sendConfigByFile(patch.getConfigId(), 2);
						player.getInventory().addItem(WEEDS, 1);
					} else if (stage == 6) {
						player.setNextAnimation(RAKE_ANIMATION);
						player.getPackets().sendConfigByFile(patch.getConfigId(), 3);
						player.getInventory().addItem(WEEDS, 1);
						player.unlock();
						if (objectId == Patches.FALADOR_FLOWER.getObjectId()) {
							player.setFaladorFlowerPatchRaked(true);
						}
						if (objectId == Patches.FALADOR_HERB.getObjectId()) {
							player.setFaladorHerbPatchRaked(true);
						}
						if (objectId == Patches.FALADOR_NORTH_ALLOTMENT.getObjectId()) {
							player.setFaladorNorthAllotmentPatchRaked(true);
						}
						if (objectId == Patches.FALADOR_SOUTH_ALLOTMENT.getObjectId()) {
							player.setFaladorSouthAllotmentPatchRaked(true);
						}
					}
					stage++;
				}
			}, 0, 1);
		} else {
			player.getPackets().sendGameMessage("You must have a rake to rake these weeds.");
			return;
		}
	}
	
	public static void plantHerbSeed(final Player player, final int seed, final int objectId) {
		final Herbs herb = Herbs.forId(seed);
		final Patches patch = Patches.forId(objectId);
		if (player.getSkills().getLevelForXp(Skills.FARMING) < herb.getReq()) {
			player.getPackets().sendGameMessage("You need a Farming level of " + herb.getReq() + " to plant this.");
			return;
		}
		if (player.getInventory().containsItem(SEED_DIBBER, 1)) {
			if (Herbs.herbs.containsKey(seed)) {
				WorldTasksManager.schedule(new WorldTask() {
					int stage;
					
					@Override
					public void run() {
						if (stage == 0) {
							player.lock();
							player.setNextAnimation(PLANT_ANIMATION);
							if (objectId == Patches.FALADOR_HERB.getObjectId()) {
								player.setFaladorHerbPatch(herb.getSeed());
							}
							player.getSkills().addXp(Skills.FARMING, herb.getPlantXp());
							player.getPackets().sendConfigByFile(patch.getConfigId(), herb.getConfigId());
							player.getInventory().deleteItem(herb.getSeed(), 1);
							player.unlock();
						} else if (stage == 3) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), herb.getConfigId() + 1);
						} else if (stage == 6) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), herb.getConfigId() + 2);
						} else if (stage == 9) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), herb.getConfigId() + 3);
						} else if (stage == 12) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), herb.getConfigId() + 4);
						}
						stage++;
					}
				}, 0, 1);
			} else {
				player.getPackets().sendGameMessage("You can't plant that here.");
				return;
			}
		} else {
			player.getPackets().sendGameMessage("You must have a seed dibber to plant these seeds.");
			return;
		}
	}
	
	public static void plantAllotmentSeed(final Player player, final int seed, final int objectId) {
		final Allotments allotment = Allotments.forId(seed);
		final Patches patch = Patches.forId(objectId);
		if (player.getSkills().getLevelForXp(Skills.FARMING) < allotment.getReq()) {
			player.getPackets().sendGameMessage("You need a Farming level of " + allotment.getReq() + " to plant this.");
			return;
		}
		if (player.getInventory().containsItem(SEED_DIBBER, 1) && player.getInventory().containsItem(allotment.getSeed(), 3)) {
			if (Allotments.allotments.containsKey(seed)) {
				WorldTasksManager.schedule(new WorldTask() {
					int stage;
					
					@Override
					public void run() {
						if (stage == 0) {
							player.lock();
							player.setNextAnimation(PLANT_ANIMATION);
							if (objectId == Patches.FALADOR_NORTH_ALLOTMENT.getObjectId()) {
								player.setFaladorNorthAllotmentPatch(allotment.getSeed());
							} else if (objectId == Patches.FALADOR_SOUTH_ALLOTMENT.getObjectId()) {
								player.setFaladorSouthAllotmentPatch(allotment.getSeed());
							}
							player.getSkills().addXp(Skills.FARMING, allotment.getPlantXp());
							player.getPackets().sendConfigByFile(patch.getConfigId(), allotment.getConfigId());
							player.getInventory().deleteItem(allotment.getSeed(), 3);
							player.unlock();
						} else if (stage == 3 && allotment.getStages() >= 1) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), allotment.getConfigId() + 1);
						} else if (stage == 6 && allotment.getStages() >= 2) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), allotment.getConfigId() + 2);
						} else if (stage == 9 && allotment.getStages() >= 3) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), allotment.getConfigId() + 3);
						} else if (stage == 12 && allotment.getStages() >= 4) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), allotment.getConfigId() + 4);
						} else if (stage == 15 && allotment.getStages() >= 5) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), allotment.getConfigId() + 5);
						} else if (stage == 18 && allotment.getStages() >= 6) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), allotment.getConfigId() + 6);
						} else if (stage == 21 && allotment.getStages() >= 7) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), allotment.getConfigId() + 7);
						} else if (stage == 24 && allotment.getStages() >= 8) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), allotment.getConfigId() + 8);
						}
						stage++;
					}
				}, 0, 1);
			} else {
				player.getPackets().sendGameMessage("You can't plant that here.");
				return;
			}
		} else if (!player.getInventory().containsItem(SEED_DIBBER, 1)) {
			player.getPackets().sendGameMessage("You must have a seed dibber to plant these seeds.");
			return;
		} else if (!player.getInventory().containsItem(allotment.getSeed(), 3)) {
			player.getPackets().sendGameMessage("You must have at least 3 seeds to plant.");
			return;
		}
	}
	
	public static void plantFlowerSeed(final Player player, final int seed, final int objectId) {
		final Flowers flower = Flowers.forId(seed);
		final Patches patch = Patches.forId(objectId);
		if (player.getSkills().getLevelForXp(Skills.FARMING) < flower.getReq()) {
			player.getPackets().sendGameMessage("You need a Farming level of " + flower.getReq() + " to plant this.");
			return;
		}
		if (player.getInventory().containsItem(SEED_DIBBER, 1)) {
			if (Flowers.flowers.containsKey(seed)) {
				WorldTasksManager.schedule(new WorldTask() {
					int stage;
					
					@Override
					public void run() {
						if (stage == 0) {
							player.lock();
							player.setNextAnimation(PLANT_ANIMATION);
							if (objectId == Patches.FALADOR_FLOWER.getObjectId()) {
								player.setFaladorFlowerPatch(flower.getSeed());
							}
							player.getSkills().addXp(Skills.FARMING, flower.getPlantXp());
							player.getPackets().sendConfigByFile(patch.getConfigId(), flower.getConfigId());
							player.getInventory().deleteItem(flower.getSeed(), 1);
							player.unlock();
						} else if (stage == 3 && flower.getStages() >= 1) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), flower.getConfigId() + 1);
						} else if (stage == 6 && flower.getStages() >= 2) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), flower.getConfigId() + 2);
						} else if (stage == 12 && flower.getStages() >= 3) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), flower.getConfigId() + 3);
						} else if (stage == 15 && flower.getStages() >= 4) {
							player.getPackets().sendConfigByFile(patch.getConfigId(), flower.getConfigId() + 4);
						}
						stage++;
					}
				}, 0, 1);
			} else {
				player.getPackets().sendGameMessage("You can't plant that here.");
				return;
			}
		} else {
			player.getPackets().sendGameMessage("You must have a seed dibber to plant these seeds.");
			return;
		}
	}
	
	public static void harvestHerb(final Player player, final int objectId, int seed) {
		final Herbs herb = Herbs.forId(seed);
		final Patches patch = Patches.forId(objectId);
		if (player.getInventory().containsItem(SECATEURS, 1)) {
			int amount = Utils.random(18);
			double xp = amount * herb.getHarvestXp();
			if (amount < 3 && player.getInventory().getFreeSlots() >= 3) {
				player.setNextAnimation(PICK_HERB);
				player.getSkills().addXp(Skills.FARMING, xp * 3);
				player.getInventory().addItem(herb.getProduct(), 3);
				player.getPackets().sendConfigByFile(patch.configId, 0);
				if (objectId == Patches.FALADOR_HERB.getObjectId()) {
					player.setFaladorHerbPatch(-1);
					player.setFaladorHerbPatchRaked(false);
				}
			} else if (player.getInventory().getFreeSlots() < amount) {
				amount = player.getInventory().getFreeSlots();
				player.setNextAnimation(PICK_HERB);
				player.getSkills().addXp(Skills.FARMING, xp);
				player.getInventory().addItem(herb.getProduct(), amount);
				player.getPackets().sendConfigByFile(patch.configId, 0);
				if (objectId == Patches.FALADOR_HERB.getObjectId()) {
					player.setFaladorHerbPatch(-1);
					player.setFaladorHerbPatchRaked(false);
				}
			} else {
				player.setNextAnimation(PICK_HERB);
				player.getSkills().addXp(Skills.FARMING, xp);
				player.getInventory().addItem(herb.getProduct(), amount);
				player.getPackets().sendConfigByFile(patch.configId, 0);
				if (objectId == Patches.FALADOR_HERB.getObjectId()) {
					player.setFaladorHerbPatch(-1);
					player.setFaladorHerbPatchRaked(false);
				}
			}
		} else {
			player.getPackets().sendGameMessage("You must have secateurs to harvest these herbs.");
			return;
		}
	}
	
	public static void harvestAllotment(final Player player, final int objectId, int seed) {
		final Allotments allotment = Allotments.forId(seed);
		final Patches patch = Patches.forId(objectId);
		if (player.getInventory().containsItem(SPADE, 1)) {
			int amount = Utils.random(28);
			double xp = amount * allotment.getHarvestXp();
			if (amount < 3 && player.getInventory().getFreeSlots() >= 3) {
				player.setNextAnimation(PICK_ALLOTMENT);
				player.getSkills().addXp(Skills.FARMING, xp * 3);
				player.getInventory().addItem(allotment.getProduct(), 3);
				player.getPackets().sendConfigByFile(patch.configId, 0);
				if (objectId == Patches.FALADOR_NORTH_ALLOTMENT.getObjectId()) {
					player.setFaladorNorthAllotmentPatch(-1);
					player.setFaladorNorthAllotmentPatchRaked(false);
				} else if (objectId == Patches.FALADOR_SOUTH_ALLOTMENT.getObjectId()) {
					player.setFaladorSouthAllotmentPatch(-1);
					player.setFaladorSouthAllotmentPatchRaked(false);
				}
			} else if (player.getInventory().getFreeSlots() < amount) {
				amount = player.getInventory().getFreeSlots();
				player.setNextAnimation(PICK_ALLOTMENT);
				player.getSkills().addXp(Skills.FARMING, xp);
				player.getInventory().addItem(allotment.getProduct(), amount);
				player.getPackets().sendConfigByFile(patch.configId, 0);
				if (objectId == Patches.FALADOR_NORTH_ALLOTMENT.getObjectId()) {
					player.setFaladorNorthAllotmentPatch(-1);
					player.setFaladorNorthAllotmentPatchRaked(false);
				} else if (objectId == Patches.FALADOR_SOUTH_ALLOTMENT.getObjectId()) {
					player.setFaladorSouthAllotmentPatch(-1);
					player.setFaladorSouthAllotmentPatchRaked(false);
				}
			} else {
				player.setNextAnimation(PICK_ALLOTMENT);
				player.getSkills().addXp(Skills.FARMING, xp);
				player.getInventory().addItem(allotment.getProduct(), amount);
				player.getPackets().sendConfigByFile(patch.configId, 0);
				if (objectId == Patches.FALADOR_NORTH_ALLOTMENT.getObjectId()) {
					player.setFaladorNorthAllotmentPatch(-1);
					player.setFaladorNorthAllotmentPatchRaked(false);
				} else if (objectId == Patches.FALADOR_SOUTH_ALLOTMENT.getObjectId()) {
					player.setFaladorSouthAllotmentPatch(-1);
					player.setFaladorSouthAllotmentPatchRaked(false);
				}
			}
		} else {
			player.getPackets().sendGameMessage("You must have a spade to harvest this allotment.");
			return;
		}
	}
	
	public static void harvestFlower(final Player player, final int objectId, int seed) {
		final Flowers flower = Flowers.forId(seed);
		final Patches patch = Patches.forId(objectId);
		if (player.getInventory().containsItem(SPADE, 1)) {
			int amount = Utils.random(10);
			double xp = amount * flower.getHarvestXp();
			if (player.getInventory().getFreeSlots() < amount) {
				amount = player.getInventory().getFreeSlots();
				player.setNextAnimation(PICK_ALLOTMENT);
				player.getSkills().addXp(Skills.FARMING, xp);
				player.getInventory().addItem(flower.getProduct(), amount);
				player.getPackets().sendConfigByFile(patch.configId, 0);
				if (objectId == Patches.FALADOR_FLOWER.getObjectId()) {
					player.setFaladorFlowerPatch(-1);
					player.setFaladorFlowerPatchRaked(false);
				}
			} else {
				player.setNextAnimation(PICK_ALLOTMENT);
				player.getSkills().addXp(Skills.FARMING, xp);
				player.getInventory().addItem(flower.getProduct(), amount);
				player.getPackets().sendConfigByFile(patch.configId, 0);
				if (objectId == Patches.FALADOR_FLOWER.getObjectId()) {
					player.setFaladorFlowerPatch(-1);
					player.setFaladorFlowerPatchRaked(false);
				}
			}
		} else {
			player.getPackets().sendGameMessage("You must have a spade to harvest this flower.");
			return;
		}
	}
}
